/**
 * 2010(c) www.jcaramel.com
 * MENU
 * 
 * Requires:
 * jCaramel Core
 */

jCaramel.menu = {
	
	/**
	 * Creates the menu
	 * @param {jQuery} ul List to convert into menu
	 * @param {Object} settings
	 */
	_create: function(ul, settings){
		
		//Create handle
		jCaramel.createHandle(ul);
		
		//Add menu class
		ul.addClass('jc-menu');
		
		//Hide nested lists
		ul.children('li').children('ul').hide();
		
		//Assign handlers
		jCaramel.menu.assignItemHandlers(tb, ul.children('li'));

		//Prep items		
		jCaramel.menu.prep(ul, ul.children('li'));
		
		//Assign min-width
		ul.css('min-width', settings.minWidth);
		
		//Set popUp type
		jCaramel.menu.popUpType(ul, settings.popUpType);
		
		//Check if owner passed
		if(settings.owner){
			
			settings.owner.tag('context-menu', ul.tag('handle'))
				.tag('context-menu-position', settings.position)
				.unbind(settings.ownerAction, jCaramel.menu.owner_Action)
				.bind(settings.ownerAction, jCaramel.menu.owner_Action);
			
			ul.hide();
		}
		
		//Events
			[
				'open', 'close', 
			].forEach(function(evtName){ jCaramel.bind(ul, evtName, settings[evtName]); });
		
	},
	
	assignItemHandlers: function(tb, items){
		items
			.unbind('mouseenter', jCaramel.menu.item_MouseEnter)
			.mouseenter(jCaramel.menu.item_MouseEnter)
			
			.unbind('mousleave', jCaramel.menu.item_MouseLeave)
			.mouseleave(jCaramel.menu.item_MouseLeave)
			
			.unbind('click', jCaramel.menu.item_Click)
			.click(jCaramel.menu.item_Click)
	},
	
	canceller: function(evt){
		
		
		
		if(jCaramel.menu.mouseOverMenus(evt.pageX, evt.pageY)){
			return;
		}
		
		jCaramel.menu.dismiss(jCaramel.getByHandle(jQuery('body').tag('current-menu')));
	},
	
	/**
	 * Clears the popups of the siblings of specified item
	 * @param {Object} item
	 */
	clearPopUps: function(item){
		item.siblings().each(function(index){
			var sitem = jQuery(this);
			
			sitem.children('ul').hide();
			sitem.flag('opened', false);
			sitem.removeClass('selected');
		});
	},
	
	/**
	 * Hides the dialog
	 * @param {jQuery} ul
	 */
	dismiss: function(ul){
		
		ul.hide();
		
		jQuery('body').flag('current-menu', '');
		
		jQuery(document).unbind('click', jCaramel.menu.canceller);
	},
	
	/**
	 * Handles click of events
	 * @param {Object} evt
	 */
	item_Click: function(evt){
		
		var item = jQuery(this);
		var ul = item.parent();

		if(item.flag('sub-menu') && jCaramel.menu.popUpType(ul) == 'click'){
			
			jCaramel.menu.popUp(item);
			
			evt.stopPropagation();
		}
		
	},
	
	/**
	 * Handles MouseEnter event of items
	 * @param {jQuery} evt
	 */
	item_MouseEnter: function(evt){
		
		var item = jQuery(this);
		var ul = item.parent();

		if(!(item.hasClass('label') || item.hasClass('widget')) ){
			item.addClass('selected');
		}
		
		
		if(item.flag('sub-menu') && jCaramel.menu.popUpType(ul) == 'mouseenter'){
			
			jCaramel.menu.popUp(item);
			
			evt.stopPropagation();
			
		}else{
			jCaramel.menu.clearPopUps(item);
		}
	},
	
	/**
	 * Handles MouseLeave event of items
	 * @param {jQuery} evt
	 */
	item_MouseLeave: function(evt){
		var item = jQuery(this);
		
		if(!item.flag('opened'))
			item.removeClass('selected');	
	},
	
	/**
	 * Indicates if mouse is currently over some menu
	 * @param {int} pageX x coord of mouse relative to the edge of document
	 * @param {int} pageY y coord of mouse relative to the edge of document
	 */
	mouseOverMenus: function(pageX, pageY){
		
		//Check if click was on a menu
		var menus = jQuery('ul.jc-menu:visible');
		
		for(var i = 0; i < menus.size(); i++){
			var m = menus.eq(i);
			var offset = m.offset();
			var p = {x: pageX, y: pageY};
			var r = {x: offset.left, y:offset.top, w:m.width(), h:m.height()};
			
			//If point in rectangle, abort canceller
			if( (p.x >= r.x && p.x <= (r.x + r.w))
			&&  (p.y >= r.y && p.y <= (r.y + r.h) ) ){
				return true;
			}
			
			//alert(r.x + ", " + r.y  + ", " + r.w  + ", " + r.h)
			
		}
		false;
	},
	
	/**
	 * Handles the click on the owner
	 * @param {Object} evt
	 */
	owner_Action: function(evt){
		
		var owner = jQuery(this);
		var position = owner.tag('context-menu-position');
		var menu = jCaramel.getByHandle(owner.tag('context-menu'));
		
		if (menu.is(':visible')) {
			menu.hide();
		}
		else {
			jQuery('body').tag('current-menu', menu.tag('handle'));
			jQuery(document).bind('click', jCaramel.menu.canceller);
			jCaramel.menu.show(menu, owner, position);
		}
	},
	
	/**
	 * Pops up the sub list contained on item
	 * @param {Object} item Item that contains the popup to pop
	 * @param {Object} ul List to pop
	 */
	popUp: function(item){
		
		jCaramel.menu.clearPopUps(item);
		
		item.flag('opened', true);
		ul = item.children('ul:first');
		ul.menu({
			minWidth: item.parent().css('min-width'),
			popUpType: jCaramel.menu.popUpType(item.parent())
		});
		
		jCaramel.menu.show(ul, item, 'right', true);
		
	},
	
	/**
	 * Gets or sets the event when pop-ups (sub-menus) are displayed
	 * @param {jQuery} ul to check
	 * @param {string} eventName can be 'mouseenter' or 'click'
	 */
	popUpType: function(ul, eventName){
		
		if(typeof(eventName) == 'string'){
			ul.tag('popUpType', eventName);
		}else{
			return ul.tag('popUpType');
		}
	},
	
	/**
	 * Preps 
	 * @param {jQuery} ul to prep
	 * @param {jQuery} li items to prep 
	 */
	prep: function(ul, items){
		//Check for dropsides
		items.each(function(index){
			var li = jQuery(this);
			var ul = li.children('ul');
			
			if(ul.size() == 1 && !li.flag('sub-menu')){
				li
					.flag('sub-menu', true)
					.append( jQuery('<div>').addClass('glyph-16 glyph-dropside').addClass(jCaramel.rtl ? 'lefty': 'righty') );
			}else if(li.text() == "-"){
				li.text('').addClass('separator');
			}
			
		});
	},
	
	/**
	 * Shows the menu relative to the specified owner
	 * @param {Object} ul
	 * @param {Object} owner
	 */
	show: function(ul, owner, position, ispopup){
		
		var offset = (ispopup ? owner.position() : owner.offset());
		var top = offset.top;
		var left = offset.left;
		
		if (position == 'top'){
			top -= ul.outerHeight();
		}else if (position == 'right'){
			left += owner.outerWidth();
		}else if (position == 'bottom'){
			top += owner.outerHeight();
		}else if(position == 'left'){
			left -= ul.outerWidth();
		}
		
		//Clean selected items
		ul.children('li').each(function(){ jQuery(this).removeClass('selected') });
		
		//Hide sub-uls
		ul.children('li').children('ul').hide();
		
		//Locate ul
		ul.css({'top': top, 'left': left}).show();
		
		//Fire the 'open' event
		jCaramel.fire(owner.parent(), 'open', [ul]);
		
		
	}
};

jQuery.fn.menu = function(a, b, c){
	if (typeof(a) == 'string') {
		return jCaramel.menu[a](this, b);
	}
	else {
		settings = jQuery.extend({
			
			/**
			 * When to show pop-ups:
			 * mouseenter | click
			 */
			popUpType: 'mouseenter',
			
			/**
			 * Minimum width to be applied to menu and sub-menus.
			 */
			minWidth: 250,
			
			/**
			 * Owner of the menu. Menu will be showed when owner clicked
			 */
			owner: null,
			
			/**
			 * Name of the event that will trigger the show of the menu.
			 * Can be any name of event, the recommended are 'click' and 'mouseenter'
			 */
			ownerAction: 'click',
			
			/**
			 * Position (relative to the owner) where menu will be displayed:
			 * top | right | bottom | left
			 */
			position: 'bottom',
			
			popup: null
			
		}, a);
		
		//Create the listview
		jCaramel.menu._create(this, settings);
		
		return this;
	}
};
